#include <functional>

#include "reflect/ClassFactory.h"
#include "reflect/ClassField.h"
#include "reflect/ClassObject.h"
#include "reflect/IClassObject.h"
using namespace bin;

ClassObject::ClassObject() : m_className("") {}

ClassObject::ClassObject(const std::string& classname) : m_className(classname)
{
}

ClassObject::~ClassObject() {}

void ClassObject::set(const std::string& className)
{
    m_className = className;
}

const std::string& ClassObject::get() const
{
    return m_className;
}

void ClassObject::setField(const std::string& fieldName, const char* fieldValue)
{
    ClassField* field = Singleton<ClassFactory>::GetInstance()->getClassField(
        m_className, fieldName);
    int offset                             = field->offset();
    *(std::string*)((size_t)this + offset) = std::string(fieldValue);
}

ClassField* ClassObject::getClassField(const std::string& className, int pos)
{
    return Singleton<ClassFactory>::GetInstance()->getClassField(className,
                                                                 pos);
}

ClassField* ClassObject::getClassField(const std::string& className,
                                       const std::string& fieldName)
{
    return Singleton<ClassFactory>::GetInstance()->getClassField(className,
                                                                 fieldName);
}

int ClassObject::getFieldCount()
{
    return Singleton<ClassFactory>::GetInstance()->getClassFieldCount(
        m_className);
}

ClassField* ClassObject::getClassField(int pos)
{
    return Singleton<ClassFactory>::GetInstance()->getClassField(m_className,
                                                                 pos);
}

ClassField* ClassObject::getClassField(const std::string& fieldName)
{
    return Singleton<ClassFactory>::GetInstance()->getClassField(m_className,
                                                                 fieldName);
}

void ClassObject::classMethodCall(const std::string& methodname)
{
    ClassMethod* classmethod =
        Singleton<ClassFactory>::GetInstance()->getClassMethod(m_className,
                                                               methodname);
    uintptr_t method = classmethod->method();

    typedef std::function<void(decltype(this), int)> func;

    (*(func*)method)(this, 20);
}

ClassMethod* ClassObject::getClassMethod(int pos)
{
    return Singleton<ClassFactory>::GetInstance()->getClassMethod(m_className,
                                                                  pos);
}
